<template>
    <LayoutWrap class="bill">
        <el-form :inline="true" :model="formSearch" ref="ruleForm" class="demo-form-inline">
            <el-form-item prop="name" label="账单名称">
                <el-input
                    v-model="formSearch.name"
                    placeholder="请输入账单名称"
                    :style="{width: formInputWidth}"
                    clearable
                    @keyup.enter.native="handleSearch"
                ></el-input>
            </el-form-item>
            <el-form-item prop="daterange" label="开始时间">
                <TheElDatePicker
                    type="datetime"
                    v-model="formSearch.daterange[0]"
                    @keyup.enter.native="handleSearch"
                    placeholder="请选择还款开始时间"
                    :style="{width: formInputWidth}"
                ></TheElDatePicker>
            </el-form-item>
            <el-form-item prop="datetime" label="结束时间">
                <TheElDatePicker
                    type="datetime"
                    v-model="formSearch.daterange[1]"
                    @keyup.enter.native="handleSearch"
                    placeholder="请选择还款结束时间"
                    :style="{width: formInputWidth}"
                ></TheElDatePicker>
            </el-form-item>
        </el-form>
        <el-form :inline="true">
            <el-form-item prop="status" label="账单状态">
                <el-button-group>
                    <template v-for="(item, index) in billStatusList">
                        <el-button
                            @click="handleClickBillStatus(item.value)"
                            :class="{'is-focus': item.value === formSearch.status}"
                            :key="index"
                            style="width: 68px"
                            >{{ item.label }}</el-button
                        >
                    </template>
                </el-button-group>
            </el-form-item>
            <el-form-item prop="" label="还款时间">
                <el-button-group>
                    <template v-for="(item, index) in billDateTimeButtonList">
                        <el-button
                            @click="handleClickBillDateTime(item.value)"
                            :class="{'is-focus': handleCalcBillDateTimeIsThat(item.value)}"
                            :key="index"
                            style="width: 68px"
                            >{{ item.label }}</el-button
                        >
                    </template>
                </el-button-group>
            </el-form-item>
            <el-form-item>
                <el-button type="default" @click="handleResetTheForm">重置</el-button>
                <el-button type="primary" @click="handleSearch">查询</el-button>
            </el-form-item>
        </el-form>
        <ul class="list-head">
            <li class="list-head-item">
                <el-button
                    style="width: 150px;"
                    :disabled="!isOperation"
                    @click="centerDialogVisible = true"
                    type="primary"
                    >新建账单</el-button
                >
            </li>
            <li class="list-head-item">
                <ExcelUpload
                    style="width: 150px;"
                    :disabled="!isOperation"
                    :on-error="handleError"
                    :on-success="handleSuccess"
                    :validSheetCell="['A1', '账单导入模板']"
                    :sheetrange="[
                        [3, 3],
                        [5, 14],
                        [16, -7]
                    ]"
                    type="primary"
                    ><i class="el-icon-upload2"></i>导入账单(.csv)
                </ExcelUpload>
            </li>
            <li class="list-head-item">
                <ExcelJsonDownload
                    type="default"
                    filename="导入账单模板下载"
                    :tHeader="TemplateDownload.tHeader"
                    :filterVal="TemplateDownload.filterVal"
                    :data="TemplateDownload.data"
                    :beforeData="TemplateDownload.beforeData"
                    :afterData="TemplateDownload.afterData"
                    bookType="csv"
                >
                    <i class="el-icon-download"></i>
                    导入账单模板下载
                </ExcelJsonDownload>
            </li>
        </ul>
        <ul class="list-head" :class="{'is-mobile': isMobile}">
            <li class="list-head-item">
                <CheckedColumns
                    :checkedId="checkedId"
                    :dataSource="checkedOpts"
                    v-model="checkedValues"
                ></CheckedColumns>
            </li>
            <li class="list-head-item" v-for="(item, index) in theBillRecords" :key="index">
                <span class="subtitle">{{ item.title }}：</span>
                <span class="dark">￥{{ item.value }}</span>
            </li>
        </ul>
        <ul class="list-head">
            <li class="list-head-item">
                <el-popover placement="top" width="160" v-model="visibleUpdate">
                    <p>确认批量修改下面选中数据吗？</p>
                    <div style="text-align: right; margin: 0">
                        <el-button
                            size="mini"
                            type="text"
                            :disabled="isLoading || !isMultSelect"
                            @click="visible = false"
                            >取消</el-button
                        >
                        <el-button type="primary" size="mini" :disabled="isLoading || !isMultSelect" @click="handleOk"
                            >确定</el-button
                        >
                    </div>
                    <el-button
                        slot="reference"
                        :disabled="!multSelectPlatform || isLoading || !isMultSelect || !multSelectPlatform"
                        >确认修改</el-button
                    >
                </el-popover>
            </li>
            <li class="list-head-item">
                <el-button :disabled="isLoading || !isMultSelect" @click="handleCancel" type="default"
                    >取消选中</el-button
                >
            </li>
            <li class="list-head-item">
                <el-select
                    v-model="multSelectPlatform"
                    :disabled="isLoading || !isMultSelect"
                    filterable
                    clearable
                    placeholder="请选择借款平台"
                    style="width: 150px;"
                >
                    <el-option
                        v-for="item in optionsPlatforms"
                        :key="item._id"
                        :label="`${item.name}`"
                        :value="item.id"
                    >
                    </el-option>
                </el-select>
            </li>
        </ul>
        <TheBillTable
            ref="singleTable"
            v-loading="isLoading"
            :checkedValues="checkedValues"
            :tableData="tableData"
            :getList="getList"
            :formSearch="formSearch"
            @selection-change="handleSelectionChange"
            :optionsPlatforms="optionsPlatforms"
        ></TheBillTable>
        <CreateBill
            title="新建账单"
            @on-ok="getList"
            :visible.sync="centerDialogVisible"
            :optionsPlatforms="optionsPlatforms"
        >
        </CreateBill>
    </LayoutWrap>
</template>

<script>
// @ is an alias to /src
import {formInputWidth} from '@/styles/variables.scss';
import moment from 'moment';
import {getBillList, postBillList, getBillPlatforms, putBillsList} from '@/api/bill';
import CreateBill from '@/views/bill/CreateBill';
import ExcelJsonDownload from '@/components/ExcelJsonDownload/index';
import {BASIC_MONEY, DEFAULT_DAY, THE_MOMENT_YYYYMMDD_HHMMSS} from '@/utils/constant';
import {initDateRange} from '@/utils/utils';
import {mixinIsOperation} from '@/mixins';
import {mapGetters, mapState} from 'vuex';
import {
    handleCompleteBillRecords,
    handleGetBillStatusByText,
    handleGetTheBillTotalStatus
} from '@/views/bill/filters-bill';
import {
    getDefaultPickerOptions,
    getBillStatusOptions,
    handleGetColumns,
    BILL_STATUS_REPAYMENT,
    BILL_STATUS_SETTLED,
    BILL_STATUS_PAST_DUE,
    BILL_STATUS_TEXT_REPAYMENT,
    BILL_STATUS_TEXT_SETTLED,
    BILL_STATUS_TEXT_PAST_DUE
} from '@/views/bill/constant-bill';
import CheckedColumns from '@/components/CheckedColumns';
import {THE_CHECKED_BILL_COLUMNS} from '@/utils/list-types';
import TheBillTable from '@/views/bill/TheBillTable';
import ExcelUpload from '@/components/ExcelUpload/index';
import {getBillObjKeys} from '@/views/bill/getObjKeys';
export default {
    name: 'bill',
    components: {
        CreateBill,
        ExcelJsonDownload,
        CheckedColumns,
        ExcelUpload,
        TheBillTable
    },
    mixins: [mixinIsOperation],
    data() {
        return {
            BILL_STATUS_REPAYMENT,
            BILL_STATUS_SETTLED,
            BILL_STATUS_PAST_DUE,
            theBillRecords: [], // 账单状态统计数据

            // 新建账单弹窗
            centerDialogVisible: false,

            formInputWidth: formInputWidth,

            // 还款时间
            billDateTimeButtonList: [
                {
                    label: '全部',
                    value: null
                },
                {
                    label: '本月',
                    value: 'current'
                },
                {
                    label: '上一月',
                    value: 'pre'
                },
                {
                    label: '下一月',
                    value: 'next'
                }
            ],
            // 账单状态查询条件
            billStatusList: [
                {
                    label: '全部',
                    value: null
                },
                ...getBillStatusOptions()
            ],
            // 查询数据
            formSearch: {
                name: '', // 名称 、借款公司
                status: BILL_STATUS_REPAYMENT, // 账单状态
                daterange: [],
                count: 0, // 总条数
                pageSize: 10, // 一页多少条
                page: 1 // 当前第几页
            },
            // 列表数据
            tableData: [],

            // 日期选择器
            pickerOptions: getDefaultPickerOptions(),
            // 默认选中的数据
            checkedValues: ['from_time', 'name', 'current.status', 'current.date', 'current.cash', 'operation'],
            checkedOpts: handleGetColumns(), // 需要选择的数据[{}, {label: '', value: ''}]
            checkedId: THE_CHECKED_BILL_COLUMNS,
            TemplateDownload: {
                tHeader: ['当前期数', '还款日期', '账单状态', '本金', '利息', '备注'],
                filterVal: [],
                data: [],
                beforeData: [
                    ['账单导入模板'],
                    [''],
                    ['账号：[]'],
                    ['------------------------------------------------------------------------------------'],
                    ['ProjectName', 'Value', 'Remark（不会被录入）'],
                    ['账单名称', [' '], '必填（招商银行信用卡）'],
                    ['借款金额', [' '], ['必填（1000.00）']],
                    ['综合年化费率', [' '], ['必填（20 === 20%）']],
                    ['借款时间', [' '], ['必填（YYYY/MM/DD）']],
                    ['还款方式', [' '], ['选填（自定义,等额本金）']],
                    // ['总分期数', [' '], ['必填（12）']],
                    ['还款银行', [' '], ['必填（招商银行1234）']],
                    ['账单ID', [' '], ['（创建不填，修改必填）']],
                    ['备注', ['模板导入'], '选填（账单备注）'],
                    [''],
                    ['------------------------------------------------------------------------------------']
                ],
                afterData: [
                    ...new Array(12).fill('').map((item, index) => {
                        let defaultStatus = BILL_STATUS_TEXT_REPAYMENT;
                        const defaultDate = moment()
                            .add(index + 1, 'months')
                            .format('YYYY/MM/DD');
                        // if (index === 10) {
                        //     defaultStatus = BILL_STATUS_TEXT_SETTLED;
                        // }
                        // if (index === 11) {
                        //     defaultStatus = BILL_STATUS_TEXT_PAST_DUE;
                        // }
                        return [index + 1, defaultDate, defaultStatus, ' ', ' ', '模板导入'];
                    }),
                    ['------------------------------------------------------------------------------------'],
                    ['占位行，请勿删除该行1'],
                    ['占位行，请勿删除该行2'],
                    ['占位行，请勿删除该行3'],
                    ['占位行，请勿删除该行4'],
                    ['占位行，请勿删除该行5'],
                    ['占位行，请勿删除该行6']
                ]
            },
            optionsPlatforms: [],
            multipleSelection: [],
            multSelectPlatform: '',
            isLoading: false,
            visibleUpdate: false
        };
    },
    computed: {
        ...mapState('app', {
            isMobile: state => state.isMobile
        }),
        isMultSelect() {
            return this.multipleSelection.length > 0;
        }
    },
    created() {
        // 初始化DateRange
        // this.handleResetDateRange('current');

        this.getList();

        this.getBillPlatforms();
    },
    methods: {
        async handleOk() {
            const multSelectPlatform = this.multSelectPlatform;
            if (!multSelectPlatform) {
                this.$message({showClose: true, type: 'error', message: '请选择批量修改项'});
                return;
            }
            this.visibleUpdate = false;
            console.log('确认修改');
            this.isLoading = true;
            try {
                const newItems = this.multipleSelection.map(item => {
                    return {_id: item._id, platform: multSelectPlatform};
                });
                await putBillsList(newItems);
                this.$message({showClose: true, type: 'success', message: '批量修改成功'});
            } catch (error) {
                this.$message({showClose: true, type: 'error', message: '批量修改失败'});
                console.error(error);
            } finally {
                this.isLoading = false;
            }
            this.getList();
        },
        // 取消修改
        handleCancel() {
            this.$refs.singleTable.clearSelection();
        },
        getBillPlatforms() {
            const newItem = {page: 1, pageSize: 1000, sort: 'date', select: '_id name remark -bills'};
            return getBillPlatforms(newItem)
                .then(({data: res}) => {
                    this.optionsPlatforms = res.data;
                })
                .catch(error => {
                    console.log('error', error);
                });
        },
        handleSelectionChange(value) {
            this.visibleUpdate = false;
            this.multipleSelection = value;
            this.multSelectPlatform = '';
        },
        // 点击账单还款状态
        handleClickBillStatus(value) {
            this.formSearch.status = value;
        },
        // 点击账单还款时间
        handleClickBillDateTime(value) {
            if (!value) {
                this.formSearch.daterange = [];
                return;
            }
            this.formSearch.daterange = this.handleResetDateRange(value);
        },
        // 判断是否需要选中账单还款时间
        handleCalcBillDateTimeIsThat(value) {
            const daterange = this.formSearch.daterange;
            if (!value) {
                const data = this.$options.data();
                const formSearch = data.formSearch;

                return JSON.stringify(daterange) === JSON.stringify(formSearch.daterange);
            }
            return JSON.stringify(this.handleResetDateRange(value)) === JSON.stringify(daterange);
        },

        // 重置表单
        handleResetTheForm() {
            this.$refs['ruleForm'].resetFields();

            // 重置表单状态
            const data = this.$options.data();
            const formSearch = data.formSearch;
            this.handleClickBillStatus(formSearch.status);
        },
        // 查询按钮
        handleSearch() {
            this.formSearch = {...this.formSearch, page: 1, pageSize: 10};
            this.getList();
        },

        // 获取账单信息
        getList() {
            const {name, status, daterange, page, pageSize} = this.formSearch;
            let [startDate, endDate] = daterange || [];

            startDate = startDate || undefined; // 还款时间 开始
            endDate = endDate || undefined; // 还款时间 结束

            const newItem = {
                name: name.trim(),
                status: status,
                startDate,
                endDate,
                page,
                pageSize
            };
            this.isLoading = true;

            getBillList(newItem)
                .then(({data: res}) => {
                    if (res.status === 200) {
                        const {data = [], statData, page, pageSize, count} = res;
                        const newBills = data.map(item => {
                            const stages = item.stages;
                            // 当前账单状态
                            const current = handleGetTheBillTotalStatus(item.stages);

                            return {
                                ...item,
                                total: item.total / BASIC_MONEY,
                                total_all: item.total_all / BASIC_MONEY,
                                current: {...current, cash: current.cash / BASIC_MONEY}
                            };
                        });

                        this.tableData = newBills;

                        const theBillRecords = handleCompleteBillRecords(statData).map(item => ({
                            ...item,
                            value: item.value / BASIC_MONEY
                        }));
                        this.theBillRecords = theBillRecords;

                        this.formSearch = {...this.formSearch, page, pageSize, count};
                    } else {
                        throw new Error(res);
                    }
                })
                .catch(error => {
                    console.error(error);
                })
                .finally(() => {
                    this.isLoading = false;
                });
        },
        // 修改还款时间
        handleResetDateRange(str) {
            const defaultDateRange = this.formSearch.daterange || [];
            // eslint-disable-next-line
            const [currentStart, currentEnd] =
                defaultDateRange.length > 0 ? defaultDateRange : initDateRange(DEFAULT_DAY, DEFAULT_DAY);

            // 获取账单周期
            const today = moment(new Date()).format('DD') - 0;
            // 默认的上一个月日期
            let datePre = new Date(currentStart);
            // 默认的当一个月日期
            let dateCurrent = new Date();
            // 默认的下一个月日期
            let dateNext = new Date(currentEnd).getTime() + 3600 * 1000 * 24 * 32;
            if (today >= DEFAULT_DAY) {
                datePre = new Date(currentStart);
                dateCurrent = new Date().getTime() + 3600 * 1000 * 24 * 32;
                dateNext = new Date(currentEnd).getTime();
            }

            let daterange;
            if (str === 'pre') {
                // 上一个月
                const [preStart, preEnd] = initDateRange(DEFAULT_DAY, DEFAULT_DAY, datePre);
                daterange = [preStart, preEnd];
            } else if (str === 'current') {
                const [preStart, preEnd] = initDateRange(DEFAULT_DAY, DEFAULT_DAY, dateCurrent);
                daterange = [preStart, preEnd];
            } else {
                // 下一个月
                const [preStart, preEnd] = initDateRange(
                    DEFAULT_DAY,
                    DEFAULT_DAY,
                    new Date(dateNext).getTime() + 3600 * 1000 * 24 * 32
                );
                daterange = [preStart, preEnd];
            }
            return daterange;
        },
        // 账单导入失败
        handleError(error) {
            console.error('error', error);
            this.$message({message: error, type: 'error'});
        },
        // 账单导入成功
        async handleSuccess({results, header}) {
            try {
                const newObj = getBillObjKeys();
                const billObjHeaders = header[1];

                let newBill = {};

                results[1].forEach(item => {
                    const name = item[billObjHeaders[0]]; // 中文字段名称，“账单名称”
                    const value = item[billObjHeaders[1]]; // 字段对应的值， “信用卡账单”
                    const key = newObj[name]; // 中文对应的英文字段名称
                    if (key) {
                        newBill[key] = typeof value === 'string' ? value.trim() : value;
                    }
                });

                const tableData = results[2].map(item => {
                    const newChild = {};
                    Object.keys(item).forEach(child => {
                        const key = newObj[child];
                        if (key) {
                            const value = item[child];
                            newChild[key] = typeof value === 'string' ? value.trim() : value;
                        }
                    });
                    return newChild;
                });
                // YYYY/MM/DD 正则匹配
                // eslint-disable-next-line max-len
                const regDate = /^\d{4}\/\d{1,2}\/\d{1,2}$/;

                // https://www.cnblogs.com/hyunbar/p/10083532.html
                // ^(([1-9]{1}\d*)|(0{1}))(\.\d{0,2})?$  保留0，1，2位小数点的字符串
                const regNum = /^(([1-9]{1}\d*)|(0{1}))(\.\d{0,2})?$/;

                if (
                    tableData.some(
                        i => i.date === '' || !(regDate.test(i.date) && new Date(i.date).toString() !== 'Invalid Date')
                    )
                ) {
                    this.$message({showClose: true, type: 'error', message: '分期时间格式不正确'});
                    return;
                }

                const target = tableData.find(
                    i =>
                        // eslint-disable-next-line operator-linebreak
                        i.principal === '' ||
                        // eslint-disable-next-line operator-linebreak
                        i.interest === '' ||
                        // eslint-disable-next-line operator-linebreak
                        !regNum.test(i.principal) ||
                        !regNum.test(i.interest)
                );

                if (target) {
                    this.$message({showClose: true, type: 'error', message: '分期利息或本金格式不正确'});
                    return;
                }

                newBill.stages = tableData.map(item => {
                    const principal = (item.principal * BASIC_MONEY).toFixed(2) - 0;
                    const interest = (item.interest * BASIC_MONEY).toFixed(2) - 0;
                    return {
                        ...item,
                        date: new Date(item.date),
                        stage: item.stage - 0,
                        status: handleGetBillStatusByText(item.status),
                        principal,
                        interest,
                        cash: (principal + interest).toFixed(2) - 0
                    };
                });

                if (!newBill.name) {
                    this.$message({showClose: true, type: 'error', message: '账单名称为空'});
                    return;
                }

                if (
                    // eslint-disable-next-line operator-linebreak
                    !newBill.from_time ||
                    !(
                        newBill.from_time && // eslint-disable-line
                        regDate.test(newBill.from_time) && // eslint-disable-line
                        new Date(newBill.from_time).toString() !== 'Invalid Date'
                    )
                ) {
                    this.$message({showClose: true, type: 'error', message: '借款时间格式不正确'});
                    return;
                }

                if (!/^(([1-9]{1}\d*)|(0{1}))(\.\d{0,3})?$/.test(newBill.rate)) {
                    this.$message({showClose: true, type: 'error', message: '综合年化费率格式不正确'});
                    return;
                }

                if (newBill.bank.length < 5 || !/[0-9]{4}/.test(newBill.bank.slice(-4))) {
                    this.$message({showClose: true, type: 'error', message: '还款银行格式不正确'});
                    return;
                }

                if (!regNum.test(newBill.total)) {
                    this.$message({showClose: true, type: 'error', message: '借款金额格式不正确'});
                    return;
                }

                newBill = {
                    ...newBill,
                    rate: newBill.rate - 0,
                    total: newBill.total * BASIC_MONEY,
                    bank: newBill.bank.slice(0, -4),
                    bank_number: newBill.bank.slice(-4),
                    start_time: newBill.stages[0].date,
                    stage_total: newBill.stages.length,
                    from_time: new Date(newBill.from_time),
                    total_all: newBill.stages.reduce((t, acc) => t + acc.cash, 0)
                };

                const {data: res} = await postBillList(newBill);
                if (res.status === 201) {
                    this.$message({showClose: true, type: 'success', message: '账单导入成功'});
                    this.getList();
                } else {
                    throw new Error(res);
                }
            } catch (error) {
                console.log('error', error);
                this.$message({showClose: true, type: 'error', message: '账单导入失败'});
            }
        }
    }
};
</script>
